import type { Instruction } from '@/types/AIResponse'
import Graphic from '@arcgis/core/Graphic'
import * as geometryEngine from '@arcgis/core/geometry/geometryEngine.js'
import SimpleFillSymbol from '@arcgis/core/symbols/SimpleFillSymbol'
import SimpleMarkerSymbol from '@arcgis/core/symbols/SimpleMarkerSymbol'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getTargetLayer, lineLayer, showLayer } from './mapLayers'
import { watch } from 'vue'
import { getPoiListByLocation, POI_TYPE, type PoiItem } from './webAPI'

// 处理添加要素
// 处理添加要素
export const handleAddFeature = (
  instruction: Instruction,
  view: __esri.MapView,
  sketchViewModel: __esri.SketchViewModel,
  tempGraphic: Graphic | null,
  setTempGraphic: (graphic: Graphic) => void,
  setCurrentInstruction: (instruction: Instruction) => void,
  initFeatureFormData: (layerType: string, aiAttributes: any) => void,
  setFeatureFormTitle: (title: string) => void,
  setFeatureFormVisible: (visible: boolean) => void,
  featureFormVisible: boolean,
  featureFormData: any,
): Promise<{ geometry?: any; attributes?: any } | undefined> => {
  return new Promise(async (resolve, reject) => {
    try {
      setCurrentInstruction(instruction)
      ElMessage.success('请点击地图添加要素，双击完成确认')

      // 根据要素类型确定绘图工具
      const toolMap = {
        POLYGON: 'polygon',
        LINE: 'polyline',
        POINT: 'point',
      } as const

      const tool = toolMap[instruction.layerType]
      if (!tool) return reject(new Error('未知图层类型'))

      // 监听对话框关闭事件
      const unwatch = watch(
        () => featureFormVisible,
        (visible) => {
          if (!visible) {
            unwatch() // 取消监听
            // 如果表单数据为空，说明用户取消了操作
            if (Object.keys(featureFormData).length === 0) {
              showLayer.graphics.remove(tempGraphic!)
              reject(new Error('用户取消操作'))
            } else {
              console.log('用户确认添加要素')
              // 用户成功添加要素，调用resolve完成Promise
              showLayer.graphics.remove(tempGraphic!)
              resolve({})
            }
          }
        },
      )

      // 设置绘图完成监听器
      const createHandler = async (event: __esri.SketchViewModelCreateEvent) => {
        if (event.state === 'complete') {
          sketchViewModel.removeHandles('create')

          // 处理图形完成
          setTempGraphic(event.graphic)
          const aiAttributes = instruction.params.attributes!
          const layerType = instruction.layerType

          // 根据要素类型初始化表单数据
          initFeatureFormData(layerType, aiAttributes)

          // 显示属性编辑对话框
          setFeatureFormTitle(
            aiAttributes.name
              ? `添加要素: ${aiAttributes.name}`
              : `添加${layerType === 'POLYGON' ? '面' : layerType === 'LINE' ? '线' : '点'}要素`,
          )
          setFeatureFormVisible(true)
          showLayer.graphics.remove(tempGraphic!)
          // 返回结果数据，包含几何信息和属性
          resolve({
            geometry: event.graphic.geometry,
            attributes: aiAttributes,
          })
        }
      }

      sketchViewModel.on('create', createHandler)
      sketchViewModel.create(tool)
    } catch (error) {
      reject(error)
    }
  })
}

// 处理更新要素
export const handleUpdateFeature = async (
  instruction: Instruction,
  view: __esri.MapView,
  featureFormData: any,
  setFeatureFormData: (data: any) => void,
  setFeatureFormTitle: (title: string) => void,
  setFeatureFormVisible: (visible: boolean) => void,
  featureFormVisible: boolean,
) => {
  const layer = getTargetLayer(instruction.layerType)
  const layerType = instruction.layerType

  // 步骤1：用户点选要素
  const selectedFeature = await new Promise<Graphic>((resolve) => {
    ElMessage.info('请点击要修改的要素')

    const handler = view.on('click', async (event) => {
      const hitResult = (await view.hitTest(event)).results as __esri.MapViewGraphicHit[]
      const feature = hitResult.find((r) => r.graphic?.layer === layer)?.graphic
      if (feature) {
        handler.remove()
        resolve(feature)
      }
    })
  })

  // 步骤2：初始化表单数据
  setFeatureFormData({ ...selectedFeature.attributes })

  // 设置对话框标题
  switch (layerType) {
    case 'POINT':
      setFeatureFormTitle(`修改点要素: ${featureFormData.BuildingName || ''}`)
      // 确保点要素的必要字段存在
      if (!featureFormData.BuildingName) featureFormData.BuildingName = ''
      if (!featureFormData.BuildingType) featureFormData.BuildingType = ''
      if (!featureFormData.description) featureFormData.description = ''
      break
    case 'LINE':
      setFeatureFormTitle(`修改线要素: ${featureFormData.RoadName || ''}`)
      // 确保线要素的必要字段存在
      if (!featureFormData.RoadName) featureFormData.RoadName = ''
      if (!featureFormData.RoadType) featureFormData.RoadType = ''
      if (!featureFormData.description) featureFormData.description = ''
      break
    case 'POLYGON':
      setFeatureFormTitle(`修改面要素: ${featureFormData.AreaName || ''}`)
      // 确保面要素的必要字段存在
      if (!featureFormData.AreaName) featureFormData.AreaName = ''
      if (!featureFormData.ServiceType) featureFormData.ServiceType = ''
      break
  }

  // 确保创建时间字段存在
  if (!featureFormData.createdAtTime) {
    featureFormData.createdAtTime = new Date().toISOString()
  }

  // 显示编辑对话框
  setFeatureFormVisible(true)

  // 等待用户提交或取消
  return new Promise<void>((resolve, reject) => {
    const unwatch = watch(
      () => featureFormVisible,
      async (visible) => {
        if (!visible) {
          unwatch() // 取消监听

          try {
            // 更新要素属性
            const updateFeatures = new Graphic({
              attributes: {
                OBJECTID: selectedFeature.attributes.OBJECTID,
                ...featureFormData,
              },
              geometry: selectedFeature.geometry,
            })

            // 提交修改
            const result = await layer.applyEdits({
              updateFeatures: [updateFeatures],
            })

            console.log('更新结果:', result)
            ElMessage.success('要素更新成功')
            resolve()
          } catch (error) {
            console.error('更新失败:', error)
            ElMessage.error(`更新失败: ${error}`)
            reject(error)
          }
        }
      },
    )
  })
}

// 处理删除要素
export const handleRemoveFeature = async (instruction: Instruction, view: __esri.MapView) => {
  const layer = getTargetLayer(instruction.layerType)
  console.log('删除要素:', instruction)
  // 步骤1：用户确认删除范围
  const confirm = await ElMessageBox.confirm(
    '请选择删除方式：(有些要素可能存在没有名称的情况，请手动选择删除)',
    '删除要素',
    {
      distinguishCancelAndClose: true,
      confirmButtonText: '按名称删除',
      cancelButtonText: '手动选择',
      type: 'warning',
    },
  ).catch((action) => action)

  // 步骤2-A：按名称删除
  if (confirm === 'confirm') {
    // 根据图层类型选择正确的字段名
    let fieldName = ''
    switch (instruction.layerType) {
      case 'POINT':
        fieldName = 'BuildingName'
        break
      case 'LINE':
        fieldName = 'RoadName'
        break
      case 'POLYGON':
        fieldName = 'AreaName'
        break
    }

    // 先查询要删除的要素
    const queryResult = await layer.queryFeatures({
      where: `${fieldName} = '${instruction.params.attributes?.name}'`,
      outFields: ['*'],
    })

    // 检查是否有匹配的要素
    if (queryResult.features.length === 0) {
      ElMessage.warning('未找到要删除的要素')
      return
    }

    // 执行删除操作
    const deleteResult = await layer.applyEdits({
      deleteFeatures: queryResult.features,
    })

    // 检查删除结果
    if (deleteResult.deleteFeatureResults.length > 0) {
      ElMessage.success(`成功删除${deleteResult.deleteFeatureResults.length}个要素`)
    } else {
      ElMessage.warning('删除操作未成功')
    }
  }
  // 步骤2-B：手动选择删除
  else {
    const feature = await new Promise<Graphic>((resolve) => {
      ElMessage.info('请点击要删除的要素')
      view.on('click', async (event) => {
        const hitResult = (await view.hitTest(event)).results as __esri.MapViewGraphicHit[]
        const feature = hitResult.find((r) => r.graphic?.layer === layer)?.graphic
        if (feature) resolve(feature)
      })
    })

    await layer.applyEdits({
      deleteFeatures: [feature],
    })
  }

  ElMessage.success('删除操作完成')
}

// 处理创建缓冲区
export const handleCreateBuffer = async (instruction: Instruction, view: __esri.MapView) => {
  try {
    // 根据图层类型确定要素类型和目标图层
    const layerType = instruction.layerType;
    const targetLayer = getTargetLayer(layerType);
    const featureTypeName = layerType === 'POLYGON' ? '区域' : layerType === 'LINE' ? '道路' : '点';

    // 步骤1：选择要素
    const feature = await new Promise<Graphic>((resolve) => {
      ElMessage.info(`请点击要创建缓冲区的${featureTypeName}`)
      view.on('click', async (event) => {
        const hitResult = (await view.hitTest(event)).results as __esri.MapViewGraphicHit[]
        const feature = hitResult.find((r) => r.graphic?.layer === targetLayer)?.graphic
        feature ? resolve(feature) : ElMessage.warning(`请选择${featureTypeName}要素`)
      })
    })

    // 步骤2：生成缓冲区
    const bufferDistance = instruction.params.bufferParams?.distance || 100; // 默认100米

    // 确保几何对象存在
    if (!feature.geometry) {
      throw new Error('要素几何对象不存在');
    }

    const buffer = geometryEngine.geodesicBuffer(
      feature.geometry,
      bufferDistance,
      'meters',
      true,
    )

    const symbol = new SimpleFillSymbol({
      color: [0, 255, 0, 0.9],
      outline: {
        color: [139, 0, 0],
        width: 2,
      },
    })

    // 获取要素名称
    let featureName = '';
    if (layerType === 'POLYGON') {
      featureName = feature.attributes.AreaName || '未命名区域';
    } else if (layerType === 'LINE') {
      featureName = feature.attributes.RoadName || '未命名道路';
    } else {
      featureName = feature.attributes.BuildingName || '未命名点';
    }

    showLayer.add(
      new Graphic({
        geometry: buffer as __esri.Polygon,
        symbol,
        attributes: {
          featureName: featureName,
          featureType: featureTypeName,
          bufferDistance: bufferDistance
        },
      }),
    )

    ElMessage.success(`已创建${featureTypeName}缓冲区`)
  } catch {
    ElMessage.error('操作取消或失败')
  }
}

// 处理查询要素
export const handleQueryFeature = async (
  instruction: Instruction,
  view: __esri.MapView,
  setAttributes: (attrs: any) => void,
  setDialogTitle: (title: string) => void,
  setDialogVisible: (visible: boolean) => void,
  highlightHandle: __esri.Handles,
): Promise<{ attributes?: any; features?: any[]; geometryInfo?: any }> => {
  const layer = getTargetLayer(instruction.layerType)

  // 处理查询条件，转换为正确的字段名
  let condition = instruction.params.queryParams?.condition || '1=1'

  // 如果查询条件中包含name字段，则根据图层类型替换为正确的字段名
  if (condition.includes('name')) {
    let fieldName = ''
    switch (instruction.layerType) {
      case 'POINT':
        fieldName = 'BuildingName'
        break
      case 'LINE':
        fieldName = 'RoadName'
        break
      case 'POLYGON':
        fieldName = 'AreaName'
        break
    }
    // 替换查询条件中的name为正确的字段名
    condition = condition.replace(/name/gi, fieldName)
  }

  const features = await layer.queryFeatures({
    where: condition,
    outFields: ['*'],
    returnGeometry: true,
  })

  if (features.features.length === 0) {
    ElMessage.warning('未找到符合条件的要素')
    return { attributes: {}, features: [], geometryInfo: null }
  }

  // 获取查询到的要素属性
  const featureAttributes = features.features[0].attributes

  // 设置UI显示
  setAttributes(featureAttributes)
  setDialogTitle(`要素属性 - ${getFeatureTitle(instruction.layerType, featureAttributes)}`)

  // 高亮显示查询到的要素
  highlightHandle.removeAll()
  const featureLayerView = (await view.whenLayerView(
    getTargetLayer(instruction.layerType)!,
  )) as __esri.FeatureLayerView
  const highlight = featureLayerView.highlight(features.features[0])
  highlightHandle.add(highlight)
  setDialogVisible(true)

  // 提取几何信息，根据要素类型处理
  const geometryInfo = features.features.map((f) => {
    const geometry = f.geometry
    let geoInfo: any = {
      type: geometry?.type,
      spatialReference: geometry?.spatialReference,
    }

    // 根据几何类型提取不同的信息
    if (geometry?.type === 'point') {
      const point = geometry as __esri.Point
      geoInfo.x = point.x
      geoInfo.y = point.y
      geoInfo.longitude = point.longitude
      geoInfo.latitude = point.latitude
    } else if (geometry?.type === 'polyline') {
      const polyline = geometry as __esri.Polyline
      geoInfo.paths = polyline.paths
      // 提取起点和终点
      if (polyline.paths.length > 0 && polyline.paths[0].length > 0) {
        const firstPath = polyline.paths[0]
        geoInfo.startPoint = {
          x: firstPath[0][0],
          y: firstPath[0][1],
        }
        geoInfo.endPoint = {
          x: firstPath[firstPath.length - 1][0],
          y: firstPath[firstPath.length - 1][1],
        }
      }
    } else if (geometry?.type === 'polygon') {
      const polygon = geometry as __esri.Polygon
      geoInfo.rings = polygon.rings
      // 提取中心点
      const centroid = polygon.centroid
      if (centroid) {
        geoInfo.centroid = {
          x: centroid.x,
          y: centroid.y,
          longitude: centroid.longitude,
          latitude: centroid.latitude,
        }
      }
      // 计算面积
      geoInfo.area = geometryEngine.geodesicArea(polygon, 'square-meters')
    }

    return geoInfo
  })

  // 返回查询结果，包含要素属性、几何信息和完整特征
  return {
    attributes: featureAttributes,
    geometryInfo: geometryInfo.length > 0 ? geometryInfo[0] : null,
    features: features.features.map((f) => ({
      attributes: f.attributes,
      geometry: f.geometry,
      // 提取经纬度信息，便于后续使用
      location:
        f.geometry?.type === 'point'
          ? {
              longitude: (f.geometry as __esri.Point).longitude,
              latitude: (f.geometry as __esri.Point).latitude,
            }
          : null,
    })),
  }
}

// 处理周围位置查询
export const    handleQuerySurrounding = async (
  instruction: Instruction,
  view: __esri.MapView,
  setAttributes: (attrs: any) => void,
  setDialogTitle: (title: string) => void,
  setDialogVisible: (visible: boolean) => void,
): Promise<{ poiList?: any[]; surroundingParams?: any; centerPoint?: any; poiPoints?: any[] }> => {
  try {
    // 获取查询参数
    const surroundingParams = instruction.params.surroundingParams
    if (!surroundingParams) {
      ElMessage.error('缺少周围位置查询参数')
      return { poiList: [], surroundingParams: null, centerPoint: null, poiPoints: [] }
    }

    const { longitude, latitude, facilityType, radius = 1000 } = surroundingParams

    // 显示加载提示
    ElMessage.info('正在查询周边设施，请稍候...')

    // 调用高德地图API获取周边POI
    const poiList = await getPoiListByLocation(longitude, latitude, facilityType, radius)

    if (poiList.length === 0) {
      ElMessage.warning('未找到周边设施')
      return {
        poiList: [],
        surroundingParams: surroundingParams,
        centerPoint: { longitude, latitude },
        poiPoints: [],
      }
    }

    // 在地图上标记查询中心点
    const centerPoint = {
      type: 'point',
      longitude,
      latitude,
    }

    const centerSymbol = new SimpleMarkerSymbol({
      color: [255, 0, 0],
      size: 10,
      outline: {
        color: [255, 255, 255],
        width: 2,
      },
    })

    const centerGraphic = new Graphic({
      geometry: centerPoint as any,
      symbol: centerSymbol,
    })

    showLayer.add(centerGraphic)

    // 存储所有POI点的详细信息
    const poiPoints: Array<{
      type: string
      longitude: number
      latitude: number
      poiInfo: {
        location: string
        index: number
        [key: string]: any
      }
    }> = []

    // 在地图上标记周边POI点
    poiList.forEach((poi, index) => {
      const [poiLng, poiLat] = poi.location.split(',').map(Number)

      const poiPoint = {
        type: 'point',
        longitude: poiLng,
        latitude: poiLat,
        poiInfo: { ...poi, index: index + 1 },
      }

      // 添加到POI点集合
      poiPoints.push(poiPoint)

      // 根据POI类型设置不同的颜色
      let poiColor = [0, 0, 255, 0.6] // 默认蓝色

      // 根据POI类型设置不同的颜色
      if (poi.type.includes('餐饮') || poi.type.includes('中餐') || poi.type.includes('快餐')) {
        poiColor = [76, 175, 80, 0.8] // 绿色 - 餐饮类
      } else if (
        poi.type.includes('购物') ||
        poi.type.includes('商场') ||
        poi.type.includes('超市')
      ) {
        poiColor = [255, 152, 0, 0.8] // 橙色 - 购物类
      } else if (
        poi.type.includes('医疗') ||
        poi.type.includes('医院') ||
        poi.type.includes('药店')
      ) {
        poiColor = [244, 67, 54, 0.8] // 红色 - 医疗类
      } else if (
        poi.type.includes('交通') ||
        poi.type.includes('公交') ||
        poi.type.includes('地铁')
      ) {
        poiColor = [3, 169, 244, 0.8] // 蓝色 - 交通类
      } else if (poi.type.includes('住宿') || poi.type.includes('酒店')) {
        poiColor = [156, 39, 176, 0.8] // 紫色 - 住宿类
      } else if (poi.type.includes('娱乐')) {
        poiColor = [255, 87, 34, 0.8] // 橙红色 - 娱乐类
      }

      const poiSymbol = new SimpleMarkerSymbol({
        color: poiColor,
        size: 10,
        outline: {
          color: [255, 255, 255],
          width: 1.5,
        },
      })

      const poiGraphic = new Graphic({
        geometry: poiPoint as any,
        symbol: poiSymbol,
        attributes: {
          ...poi,
          index: index + 1,
        },
      })

      showLayer.add(poiGraphic)
    })

    // 缩放到查询结果范围
    view.goTo(showLayer.graphics.toArray())

    // 显示查询结果列表
    const facilityTypeName =
      Object.entries(POI_TYPE).find(([_key, value]) => value === facilityType)?.[0] || '设施'
    setDialogTitle(`周边${facilityTypeName}查询结果 (${poiList.length}个)`)

    // 格式化POI列表数据用于显示
    const formattedPoiList = poiList.map((poi, index) => ({
      index: index + 1,
      name: poi.name,
      address: poi.address,
      distance: `${poi.distance}米`,
      type: poi.type,
      tel: poi.tel || '无',
      location: poi.location,
    }))

    setAttributes({
      poiList: formattedPoiList,
      centerLocation: `${longitude},${latitude}`,
      radius,
      facilityType: facilityTypeName,
    })

    setDialogVisible(true)
    ElMessage.success(`成功查询到${poiList.length}个周边设施`)

    // 返回详细的查询结果，包括中心点和所有POI点的位置信息
    return {
      poiList,
      surroundingParams,
      centerPoint: { longitude, latitude },
      poiPoints,
    }
  } catch (error) {
    console.error('周围位置查询失败:', error)
    ElMessage.error(`周围位置查询失败: ${error}`)
    return { poiList: [], surroundingParams: null, centerPoint: null, poiPoints: [] }
  }
}

// 获取要素标题
export const getFeatureTitle = (layerType: string, attrs: any): string => {
  switch (layerType) {
    case 'POINT':
      return attrs.BuildingName || '点要素'
    case 'LINE':
      return attrs.RoadName || '线要素'
    case 'POLYGON':
      return attrs.AreaName || '面要素'
    default:
      return '要素'
  }
}
